#include <iostream>
#include "logtxt.hpp"
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <sys/wait.h>
#include <signal.h>
using namespace std;
enum
{
    SOCKET_ERR = 1,
    BIND_ERR,
    LISTEN_ERR
};
const int backlog = 10;

class ThreadDate
{
public:
    int sockfd_;
    uint16_t port_;
    string ip_;

public:
    ThreadDate(int sockfd, const string &ip, const uint16_t port) : sockfd_(sockfd), port_(port), ip_(ip)
    {
    }
};
class TcpServer
{
private:
    uint16_t port_;
    string ip_;
    int listensockfd_;

public:
    TcpServer(const uint16_t &port, const string &ip = "0.0.0.0") : port_(port), ip_(ip)
    {
    }
    void Init()
    {
        listensockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (listensockfd_ < 0)
        {

            exit(SOCKET_ERR);
        }

        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        inet_aton(ip_.c_str(), &server.sin_addr);
        server.sin_port = htons(port_);

        socklen_t len = sizeof(server);
        int n = bind(listensockfd_, (const sockaddr *)&server, len);
        if (n < 0)
        {

            exit(BIND_ERR);
        }

        if (listen(listensockfd_, backlog) < 0) // 将主动文件描述符转化为被动描述符，监听连接请求
        {

            exit(LISTEN_ERR);
        }
    }

    void start()
    {

        while (true)
        {
            struct sockaddr_in client;
            memset(&client, 0, sizeof(client));
            socklen_t len = sizeof(client);

            // 接受连接
            int sockfd = accept(listensockfd_, (struct sockaddr *)&client, &len);

            if (sockfd < 0)
            {

                continue;
            }

            char buffer[32];
            uint16_t clientport = ntohs(client.sin_port);
            string clientip = inet_ntop(AF_INET, &(client.sin_addr), buffer, sizeof(buffer));

            //----单进程版
            Services(sockfd, clientip, clientport);
            close(sockfd);
        }
    }

    void Services(int sockfd, const string &clientip, const uint16_t &clientport)
    {
        while (true)
        {
            char buffermessage[1024];
            ssize_t s = read(sockfd, buffermessage, sizeof(buffermessage));
            if (s > 0)
            {
                buffermessage[s] = 0;
                cout << "get a client message:" << buffermessage << endl;
                string message = "server sendto message:";
                message += buffermessage;
                write(sockfd, message.c_str(), message.size());
            }
            else if (s == 0)
            {
                break;
            }
            else
            {
                cerr << "read fail" << endl;
                break;
            }
        }
    }
    ~TcpServer()
    {
        close(listensockfd_);
    }
};

void Usage(std::string proc)
{
    std::cout << "\n\rUsage: " << proc << " prot[1024]+\n"
              << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);

        exit(0);
    }
    uint16_t port = stoi(argv[1]);
    TcpServer tcpserver(port);
    tcpserver.Init();
    tcpserver.start();
    return 0;
}